#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2024/3/2 10:09
# @Author  : 1823218990@qq.com
# @File    : main
# @Software: Pycharm

import sys
import os
real_cfile = os.path.abspath(__file__)
real_path = os.path.dirname(real_cfile)
if sys.platform.startswith("win"):
    ffmpeg_bin = os.path.join(real_path, "ffmpeg\\bin\\ffmpeg.exe")
    ffprobe_bin = os.path.join(real_path, "ffmpeg\\bin\\ffprobe.exe")
else:
    raise RuntimeError("无法再该平台上运行")
sys.path.append(real_path)
try:
    from vclog import logger
    from vccmd import exe_cmd
except Exception as e:
    print(e)


class VideaCut(object):
    def __init__(self, ffmpeg=ffmpeg_bin,
                 inputfile=None,
                 outputfile=None,
                 logger=logger):
        self.ffmpeg = ffmpeg
        self.logger = logger
        self.inputfile = inputfile
        self.outputfile = outputfile
        self._name = None
        self._type = None
        self._duration = None
        if inputfile is not None:
            self._name, self._type = os.path.splitext(os.path.basename(self.inputfile))

    def usage(self):
        code = "{ffmpeg} -h".format(ffmpeg=self.ffmpeg)
        code, msg = exe_cmd(code)
        print(code)
        print(msg)

    def set_in_file(self, in_file):
        self.inputfile = in_file

    def set_out_file(self, out_file):
        self.outputfile = out_file

    def summary_info(self, fmt='json'):
        if self.inputfile is not None:
            cmd = "{ffprobe} -v quiet -print_format {format} -show_format -show_streams {input}".format(
                ffprobe=ffprobe_bin,
                input=self.inputfile,
                format=fmt
            )
            code, msg = exe_cmd(cmd)

            # TODO utf-8 gbk can not decode
            # self.logger.info(msg)

            return msg
        else:
            return None

    def get_duration(self, summary_info):
        try:
            json_info = eval(summary_info)
        except Exception as e:
            raise Exception("get_duration: {}".format(e))
        for key, value in json_info.items():
            if key == "format":
                for k, v in value.items():
                    if k == 'duration':
                        self._duration = float(v)
        return json_info

    def cut_video_by_range_time(self, start_time, end_time, timeout=600):
        """
        -ss 表示开始时间   时间格式为(00:00:30)
        -to 表示结束时间   时间格式为(00:05:30)
        """

        if start_time is None or end_time is None:
            raise Exception("{} or {} is None".format(start_time, end_time))
        cmd = "{ffmpeg} -i {input} -ss {from_time} -to {to_time} -c:v copy -c:a copy {output}".format(
            ffmpeg=self.ffmpeg, input=self.inputfile, output=self.outputfile,
            from_time=start_time, to_time=end_time
        )
        if self.inputfile.endswith(".rmvb"):
            output = self.outputfile.split('.rmvb')[0] + ".mp4"
            cmd = "{ffmpeg} -i {input} -ss {from_time} -to {to_time} -c:v libx264 -c:a aac {output}".format(
                ffmpeg=self.ffmpeg, input=self.inputfile, output=output,
                from_time=start_time, to_time=end_time
            )
        # print(cmd)
        code, msg = exe_cmd(cmd, timeout=timeout)
        if code == 0:
            self.logger.info("{} get {} to {} success".format(self.inputfile, start_time, end_time))

    def tranform_to_mp4(self, timeout=600):
        if self.inputfile is None or self.outputfile is None:
            return "{} or {} is None".format(self.inputfile, self.outputfile)

        cmd = "{ffmpeg} -i {input} -c:v libx264 -c:a aac {output}".format(ffmpeg=self.ffmpeg,
                                                                          input=self.inputfile,
                                                                          output=self.outputfile)
        self.logger.info(cmd)
        code, msg = exe_cmd(cmd, timeout=timeout)
        if code == 0:
            self.logger.info("{} to {} success".format(self.inputfile, self.outputfile))

    def tranform_rratio(self, ratio="1280x720", rate=30, timeout=600):
        """
        -r:帧率转换
        -s:视频分辨率
        -cv: -vcodec的简称
        :return:
        """
        cmd = "{ffmpeg} -y -i {input} -c:v libx264 -c:a aac -vf hqdn3d -s {ratio} -r {rate} -b:v 2048k {output}".format(
            ffmpeg=self.ffmpeg,
            input=self.inputfile,
            output=self.outputfile,
            ratio=ratio,
            rate=rate,
            logger=self.logger
        )
        code, msg = exe_cmd(cmd, timeout=timeout)
        if code == 0:
            self.logger.info("{} to {} success".format(self.inputfile, self.outputfile))
        else:
            self.logger.error(cmd)

    def merge_video_by_list(self, flist=[], timeout=600):
        """
        视频合并
        :param flist: [path/to/video1.mp4, path/to/video2.mp4]
        :param timeout:
        :return:
        """
        if len(flist) < 1:
            raise Exception("file list is empty")
        fconcat_str = "|".join(flist)  # path/to/video1.mp4|path/to/video2.mp4
        self.logger.info("concat list: {}".format(fconcat_str))
        cmd = '{ffmpeg} -i "concat:{input_list}" -fflags +genpts -c copy {output}'.format(
            ffmpeg=self.ffmpeg, output=self.outputfile, input_list=fconcat_str
        )
        code, msg = exe_cmd(cmd, timeout=timeout)
        if code == 0:
            self.logger.info("{} to {} success".format(self.inputfile, self.outputfile))
        else:
            self.logger.info(msg)
            self.logger.error(cmd)

    def merge_video_by_file(self, ffile=None, timeout=600):
        """
        视频合并
        :param ffile:ffmpeg -f concat -safe 0 -i list.txt -fflags +genpts -c copy output.mp4
        :param timeout:
        :return:
        """
        if not os.path.exists(ffile):
            raise Exception("file list not found")
        self.logger.info("concat file: {}".format(ffile))
        cmd = '{ffmpeg} -y -f concat -safe 0 -i {input_file} -fflags +genpts -c copy {output}'.format(
            ffmpeg=self.ffmpeg, output=self.outputfile, input_file=ffile
        )
        code, msg = exe_cmd(cmd, timeout=timeout)
        if code == 0:
            self.logger.info("{} to {} success".format(self.inputfile, self.outputfile))
        else:
            self.logger.info(msg)
            self.logger.error(cmd)

    def get_head_tail_video(self, name, duration, start_time, end_time, timeout=600):
        # cut head

        output_dir = os.path.dirname(self.outputfile)
        head_name = "{}_片头{}".format(name, self._type)
        cmd = "{ffmpeg} -i {input} -ss {from_time} -to {to_time} -c:v copy -c:a copy {output}".format(
            ffmpeg=self.ffmpeg, input=self.inputfile, output=os.path.join(output_dir, head_name),
            from_time=0, to_time=start_time
        )
        if self.inputfile.endswith(".rmvb"):
            head_name = "{}_片头.mp4".format(name)
            cmd = "{ffmpeg} -i {input} -ss {from_time} -to {to_time} -c:v libx264  -c:a aac {output}".format(
                ffmpeg=self.ffmpeg, input=self.inputfile, output=os.path.join(output_dir, head_name),
                from_time=0, to_time=start_time
            )

        code, msg = exe_cmd(cmd, timeout=timeout)
        if code == 0:
            self.logger.info("{} get [{} - {}] success".format(self.inputfile, start_time, end_time))
        else:
            self.logger.error("code: {}, msg: {}, cmd:{}".format(code, msg, cmd))
        # cut tail
        tail_name = "{}_片尾{}".format(name, self._type)
        cmd = "{ffmpeg} -i {input} -ss {from_time} -to {to_time} -c:v copy -c:a copy {output}".format(
            ffmpeg=self.ffmpeg, input=self.inputfile, output=os.path.join(output_dir, tail_name),
            from_time=end_time, to_time=duration
        )
        if self.inputfile.endswith(".rmvb"):
            tail_name = "{}_片尾.mp4".format(name)
            cmd = "{ffmpeg} -i {input} -ss {from_time} -to {to_time} -c:v libx264 -c:a aac {output}".format(
                ffmpeg=self.ffmpeg, input=self.inputfile, output=os.path.join(output_dir, tail_name),
                from_time=end_time, to_time=duration
            )
        code, msg = exe_cmd(cmd, timeout=timeout)
        if code == 0:
            self.logger.info("{} get  [{} - {}] success".format(self.inputfile, start_time, end_time))
        else:
            self.logger.error("code: {}, msg: {}, cmd: {}".format(code, msg, cmd))


if __name__ == '__main__':
    inputfile = "D:\\workspace\\video_opencv\\01.mp4"
    vc = VideaCut(inputfile=inputfile)
    vc.summary_info()

